package transform

import (
	"errors"
	"fmt"
	"strconv"
)

// 以下是基本类型转指针的函数，保持简洁高效
// Int 转换 int 为 *int
func Int(n int) *int {
	return &n
}

// Int8 转换 int8 为 *int8
func Int8(n int8) *int8 {
	return &n
}

// Int16 转换 int16 为 *int16
func Int16(n int16) *int16 {
	return &n
}

// Int32 转换 int32 为 *int32
func Int32(n int32) *int32 {
	return &n
}

// Int64 转换 int64 为 *int64
func Int64(n int64) *int64 {
	return &n
}

// Uint 转换 uint 为 *uint
func Uint(n uint) *uint {
	return &n
}

// Uint8 转换 uint8 为 *uint8
func Uint8(n uint8) *uint8 {
	return &n
}

// Uint16 转换 uint16 为 *uint16
func Uint16(n uint16) *uint16 {
	return &n
}

// Uint32 转换 uint32 为 *uint32
func Uint32(n uint32) *uint32 {
	return &n
}

// Uint64 转换 uint64 为 *uint64
func Uint64(n uint64) *uint64 {
	return &n
}

// Float32 转换 float32 为 *float32
func Float32(n float32) *float32 {
	return &n
}

// Float64 转换 float64 为 *float64
func Float64(n float64) *float64 {
	return &n
}

// 以下是增强功能：安全的类型转换与边界检查

// SafeIntToInt8 将 int 安全转换为 *int8，检查边界
func SafeIntToInt8(n int) (*int8, error) {
	if n < -128 || n > 127 {
		return nil, fmt.Errorf("int %d 超出 int8 范围 [-128, 127]", n)
	}
	val := int8(n)
	return &val, nil
}

// SafeIntToInt16 将 int 安全转换为 *int16，检查边界
func SafeIntToInt16(n int) (*int16, error) {
	if n < -32768 || n > 32767 {
		return nil, fmt.Errorf("int %d 超出 int16 范围 [-32768, 32767]", n)
	}
	val := int16(n)
	return &val, nil
}

// SafeIntToInt32 将 int 安全转换为 *int32，检查边界
func SafeIntToInt32(n int) (*int32, error) {
	if n < -2147483648 || n > 2147483647 {
		return nil, fmt.Errorf("int %d 超出 int32 范围 [-2147483648, 2147483647]", n)
	}
	val := int32(n)
	return &val, nil
}

func SafeUint64ToInt64(n uint64) (*int64, error) {
	// int64 正确的范围常量
	const minInt64 = -9223372036854775808
	const maxInt64 = 9223372036854775807

	// 检查 uint64 值是否在 int64 可表示的范围内
	if n > uint64(maxInt64) {
		return nil, fmt.Errorf("uint64 %d 超出 int64 范围 [%d, %d]", n, minInt64, maxInt64)
	}
	val := int64(n)
	return &val, nil
}

// SafeFloat64ToFloat32 将 float64 安全转换为 *float32，检查边界
func SafeFloat64ToFloat32(n float64) (*float32, error) {
	if n < -3.4028234663852885981170418348451692544e+38 ||
		n > 3.4028234663852885981170418348451692544e+38 {
		return nil, fmt.Errorf("float64 %v 超出 float32 范围", n)
	}
	val := float32(n)
	// 检查是否发生精度损失（可选）
	if float64(val) != n {
		return &val, fmt.Errorf("float64 %v 转换为 float32 时发生精度损失", n)
	}
	return &val, nil
}

// 以下是处理"零值/空值"场景的函数

// IntOrNil 如果值为0则返回nil，否则返回指针
func IntOrNil(n int) *int {
	if n == 0 {
		return nil
	}
	return &n
}

// Float64OrNil 如果值为0则返回nil，否则返回指针
func Float64OrNil(n float64) *float64 {
	if n == 0 {
		return nil
	}
	return &n
}

// IntPtr 从指针获取值，处理nil情况
func IntPtr(ptr *int) int {
	if ptr == nil {
		return 0
	}
	return *ptr
}

// Float64Ptr 从指针获取值，处理nil情况
func Float64Ptr(ptr *float64) float64 {
	if ptr == nil {
		return 0
	}
	return *ptr
}

// 基础错误定义
var (
	ErrNotANumber = errors.New("输入不是有效的数字")
	ErrOutOfRange = errors.New("数字超出目标类型范围")
)

// ParseInt32Ptr 将字符串转换为 *int32，同时验证有效性
func ParseInt32Ptr(s string) (*int32, error) {
	// 先解析为 int64 进行范围检查（避免直接解析到 int32 可能的溢出）
	n, err := strconv.ParseInt(s, 10, 64)
	if err != nil {
		if numErr, ok := err.(*strconv.NumError); ok {
			switch numErr.Err {
			case strconv.ErrSyntax:
				return nil, ErrNotANumber
			case strconv.ErrRange:
				return nil, ErrOutOfRange
			}
		}
		return nil, fmt.Errorf("转换失败: %w", err)
	}

	// 检查是否在 int32 范围内
	if n < -2147483648 || n > 2147483647 {
		return nil, fmt.Errorf("%w: int32 范围为 [-2147483648, 2147483647], 输入值为 %d", ErrOutOfRange, n)
	}

	val := int32(n)
	return &val, nil
}

// SafeIntToInt32Ptr 将 int 转换为 *int32，带范围检查
func SafeIntToInt32Ptr(n int) (*int32, error) {
	if n < -2147483648 || n > 2147483647 {
		return nil, fmt.Errorf("%w: int32 范围为 [-2147483648, 2147483647], 输入值为 %d", ErrOutOfRange, n)
	}
	val := int32(n)
	return &val, nil
}

// SafeInt64ToInt32Ptr 将 int64 转换为 *int32，带范围检查
func SafeInt64ToInt32Ptr(n int64) (*int32, error) {
	if n < -2147483648 || n > 2147483647 {
		return nil, fmt.Errorf("%w: int32 范围为 [-2147483648, 2147483647], 输入值为 %d", ErrOutOfRange, n)
	}
	val := int32(n)
	return &val, nil
}

// Int32OrNil 若值为 0 则返回 nil，否则返回 int32 指针
func Int32OrNil(n int32) *int32 {
	if n == 0 {
		return nil
	}
	return &n
}

// Int32Ptr 安全获取 *int32 的值，nil 时返回 0
func Int32Ptr(ptr *int32) int32 {
	if ptr == nil {
		return 0
	}
	return *ptr
}

// IsInt32 判断字符串是否为有效的 int32 范围内的整数
func IsInt32(s string) bool {
	n, err := strconv.ParseInt(s, 10, 64)
	if err != nil {
		return false
	}
	return n >= -2147483648 && n <= 2147483647
}

// ParseIntPtr 将字符串转换为*int，同时验证是否为有效整数
func ParseIntPtr(s string) (*int, error) {
	n, err := strconv.Atoi(s)
	if err != nil {
		if numErr, ok := err.(*strconv.NumError); ok {
			switch numErr.Err {
			case strconv.ErrSyntax:
				return nil, ErrNotANumber
			case strconv.ErrRange:
				return nil, ErrOutOfRange
			}
		}
		return nil, fmt.Errorf("转换失败: %w", err)
	}
	return &n, nil
}

// ParseInt64Ptr 将字符串转换为*int64，同时验证是否为有效整数
func ParseInt64Ptr(s string) (*int64, error) {
	n, err := strconv.ParseInt(s, 10, 64)
	if err != nil {
		if numErr, ok := err.(*strconv.NumError); ok {
			switch numErr.Err {
			case strconv.ErrSyntax:
				return nil, ErrNotANumber
			case strconv.ErrRange:
				return nil, ErrOutOfRange
			}
		}
		return nil, fmt.Errorf("转换失败: %w", err)
	}
	return &n, nil
}

// ParseUint64Ptr 将字符串转换为*uint64，同时验证是否为有效无符号整数
func ParseUint64Ptr(s string) (*uint64, error) {
	n, err := strconv.ParseUint(s, 10, 64)
	if err != nil {
		if numErr, ok := err.(*strconv.NumError); ok {
			switch numErr.Err {
			case strconv.ErrSyntax:
				return nil, ErrNotANumber
			case strconv.ErrRange:
				return nil, ErrOutOfRange
			}
		}
		return nil, fmt.Errorf("转换失败: %w", err)
	}
	return &n, nil
}

// ParseFloat64Ptr 将字符串转换为*float64，同时验证是否为有效浮点数
func ParseFloat64Ptr(s string) (*float64, error) {
	n, err := strconv.ParseFloat(s, 64)
	if err != nil {
		if numErr, ok := err.(*strconv.NumError); ok {
			switch numErr.Err {
			case strconv.ErrSyntax:
				return nil, ErrNotANumber
			case strconv.ErrRange:
				return nil, ErrOutOfRange
			}
		}
		return nil, fmt.Errorf("转换失败: %w", err)
	}
	return &n, nil
}

// IsNumber 判断字符串是否为有效的数字（整数或浮点数）
func IsNumber(s string) bool {
	// 尝试解析整数
	_, err := strconv.Atoi(s)
	if err == nil {
		return true
	}

	// 尝试解析浮点数
	_, err = strconv.ParseFloat(s, 64)
	return err == nil
}

// ParseAnyNumberPtr 自动判断数字类型并转换为对应指针，返回类型信息
func ParseAnyNumberPtr(s string) (interface{}, string, error) {
	// 先尝试整数类型
	if n, err := ParseInt64Ptr(s); err == nil {
		return n, "int64", nil
	}

	// 再尝试无符号整数
	if n, err := ParseUint64Ptr(s); err == nil {
		return n, "uint64", nil
	}

	// 最后尝试浮点数
	if n, err := ParseFloat64Ptr(s); err == nil {
		return n, "float64", nil
	}

	return nil, "", ErrNotANumber
}
